package com.xiaoshuidi.cloud.module.rooms.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.oss.core.OosFileService;
import com.xiaoshuidi.cloud.framework.tenant.core.aop.TenantIgnore;
import com.xiaoshuidi.cloud.module.contract.enums.bill.OrderFeeFlowTypeEnum;
import com.xiaoshuidi.cloud.module.finance.api.order.PayOrderApi;
import com.xiaoshuidi.cloud.module.finance.api.order.dto.PayOrderCreateReqDTO;
import com.xiaoshuidi.cloud.module.finance.enums.finance.SourceBizTypeEnum;
import com.xiaoshuidi.cloud.module.member.api.user.MemberUserApi;
import com.xiaoshuidi.cloud.module.member.api.user.dto.MemberUserReqDTO;
import com.xiaoshuidi.cloud.module.member.api.user.dto.MemberUserRespDTO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.reservation.vo.*;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomel.vo.RoomelUpdateReqVO;
import com.xiaoshuidi.cloud.module.rooms.controller.app.reserve.vo.MyReservePageRespVO;
import com.xiaoshuidi.cloud.module.rooms.convert.reservation.ReservationConvert;
import com.xiaoshuidi.cloud.module.rooms.enums.*;
import com.xiaoshuidi.cloud.module.rooms.framework.config.ConfigValues;
import com.xiaoshuidi.cloud.module.rooms.framework.utils.CodeUtil;
import com.xiaoshuidi.cloud.module.rooms.framework.utils.RoomHouseUtil;
import com.xiaoshuidi.cloud.module.rooms.job.delayjob.DelayJobService;
import com.xiaoshuidi.cloud.module.rooms.mapper.RoomReceiptMapper;
import com.xiaoshuidi.cloud.module.rooms.mapper.RoomReserveWithdrawalDetailMapper;
import com.xiaoshuidi.cloud.module.rooms.mq.listener.ReadingRoomReserveImportListener;
import com.xiaoshuidi.cloud.module.rooms.mq.producer.ReserveProducer;
import com.xiaoshuidi.cloud.module.rooms.mq.producer.RoomEsProducer;
import com.xiaoshuidi.cloud.module.rooms.pojo.*;
import com.xiaoshuidi.cloud.module.rooms.repository.*;
import com.xiaoshuidi.cloud.module.rooms.service.IRoomHouseReserveService;
import com.xiaoshuidi.cloud.module.rooms.service.IRoomReservationConfigService;
import com.xiaoshuidi.cloud.module.rooms.service.RoomReceiptService;
import com.xiaoshuidi.cloud.module.rooms.vo.ExportBaseVo;
import com.xiaoshuidi.cloud.module.system.api.receipt.ReceiptConfigApi;
import com.xiaoshuidi.cloud.module.system.api.receipt.dto.ReceiptDataRespDTO;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.xiaoshuidi.cloud.module.rooms.enums.DelayJobType.DelayJobTypeEnum.DEPOSIT_PAYMENT_TERM;
import static com.xiaoshuidi.cloud.module.rooms.enums.DelayJobType.DelayJobTypeEnum.EXPIRATION_DATE;

/**
 * <p>
 * 房源预定信息 服务实现类
 * </p>
 *
 * @author Feng
 * @since 2023-05-15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class RoomHouseReserveServiceImpl implements IRoomHouseReserveService {

    private final RoomHouseReserveRepository roomHouseReserveRepository;
    private final RoomHouseRepository roomHouseRepository;
    private final RoomEsProducer roomEsProducer;
    private final RoomStateRecordRepository roomStateRecordRepository;
    private final MemberUserApi customerUserApi;
    private final CodeUtil codeUtil;
    private final ConfigValues configValues;
    private final OosFileService oosFileService;
    private final RoomLayoutRepository roomLayoutRepository;
    private final RoomHouseTypeRepository roomHouseTypeRepository;
    private final ReserveProducer reserveProducer;
    private final DelayJobService delayJobService;
    private final ReceiptConfigApi receiptConfigApi;
    private final RoomReceiptMapper roomReceiptMapper;
    private final RoomReceiptService roomReceiptService;
    private final IRoomReservationConfigService roomReservationConfigService;
    private final RoomReserveWithdrawalDetailMapper roomReserveWithdrawalDetailMapper;
    private final PayOrderApi payOrderApi;

    /**
     * 预定账单编号前缀
     */
    private final static String RESERVE_BILL_NO_PREFIX = "ZKDJZD";

    @Override
    @Transactional
    public Long create(ReserveCreateReq req) {
        //校验房源是否是空置状态
        RoomHouse house = roomHouseRepository.getById(req.getRoomHouseId());
        Assert.isTrue(ObjectUtil.isNotEmpty(house), "房源信息不存在");
        if (house.getIsLock()) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "该房源已锁定,不可预定");
        }
        List<RoomStateRecord> stateRecordList = roomStateRecordRepository.listByRoomIdAndIsCurrentState(req.getRoomHouseId());
        Optional<RoomStateRecord> emptyStateRecord = stateRecordList.stream().filter(s -> RentStatusEnum.EMPTY.getValue().equals(s.getState())).findFirst();
        Optional<RoomStateRecord> stayingInStateRecord = stateRecordList.stream().filter(s -> RentStatusEnum.STAYINGIN.getValue().equals(s.getState())).findFirst();
        if (!emptyStateRecord.isPresent()) {
            if (stayingInStateRecord.isPresent()) {
                //todo 非空置且在入住 校验合同是否一个月退租状态
            } else {
                throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "该房源不可预定");
            }
        }
        //获取当前房源预定配置
        ReservationConfigGetResp config = roomReservationConfigService.getConfig(house.getApartmentId());
        //未支付失效时间
        if(Objects.isNull(config)||config.getUnpaidLostTime()==null){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "该房源预定配置不存在");
        }
        Long unpaidLostTime = config.getUnpaidLostTime().longValue();
        //创建预定人信息
        String booker = req.getBooker();
        String bookerPhone = req.getBookerPhone();
        String cardNo = req.getCardNo();
        MemberUserReqDTO userDto = new MemberUserReqDTO();
        userDto.setMobile(bookerPhone);
        userDto.setCardNo(cardNo);
        userDto.setName(booker);
        CommonResult<MemberUserRespDTO> userResult = customerUserApi.getUserInfo(userDto);
        if (!userResult.isSuccess()) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "预定人信息创建失败");
        }
        Long bookerId = userResult.getData().getId();

        //添加预定信息为待支付状态
        RoomHouseReserve roomHouseReserve = ReservationConvert.INSTANCE.convert(req);
        roomHouseReserve.setStatus(RoomHouseReserveStatus.TO_BE_PAID.getCode());
        roomHouseReserve.setPaymentStatus(RoomHouseReservePaymentStatus.UNTREATED.getCode());
        roomHouseReserve.setBookerId(bookerId);
        roomHouseReserve.setDeptId(house.getDeptId());
        roomHouseReserve.setBillNo(codeUtil.nextCode(RESERVE_BILL_NO_PREFIX, 4));
        roomHouseReserve.setApartmentId(house.getApartmentId());
        roomHouseReserve.setDepositPaymentTerm(LocalDateTime.now().plusMinutes(unpaidLostTime));
        roomHouseReserveRepository.save(roomHouseReserve);
//        // 创建延迟任务, 处理待支付取消和已预定取消
//        long depositPaymentTermMinutes = LocalDateTimeUtil.between(LocalDateTime.now(), roomHouseReserve.getDepositPaymentTerm()).toMinutes() + 1;
//        long expirationDateMinutes = LocalDateTimeUtil.between(LocalDateTime.now(), roomHouseReserve.getExpirationDate()).toMinutes() + 1;
//        delayJobService.addDelayJob(DEPOSIT_PAYMENT_TERM, roomHouseReserve.getId(), depositPaymentTermMinutes, TimeUnit.MINUTES);
//        delayJobService.addDelayJob(EXPIRATION_DATE, roomHouseReserve.getId(), expirationDateMinutes, TimeUnit.MINUTES);
//        log.info("房间预定ID:{}加入延迟队列", roomHouseReserve.getId());
        // 创建待支付账单 - 0530确认不创建账单信息

        //锁定当前房源，不可出租
        RoomHouse roomHouse = new RoomHouse();
        roomHouse.setIsLock(Boolean.TRUE);
        roomHouse.setId(req.getRoomHouseId());
        roomHouseRepository.updateById(roomHouse);
        //推送房源锁定状态到ES
        RoomelUpdateReqVO roomelUpdateReqVO = new RoomelUpdateReqVO();
        roomelUpdateReqVO.setIsLock(Boolean.TRUE);
        roomelUpdateReqVO.setId(req.getRoomHouseId());
        roomEsProducer.updateRoomEl(roomelUpdateReqVO);
        return roomHouseReserve.getId();
    }

    @Override
    public ReserveGetResp getByRoomId(Long roomHouseId) {
        RoomHouseReserve houseReserve = roomHouseReserveRepository.getByRoomHouseId(roomHouseId);
        if (houseReserve == null) {
            return null;
        }
        ReserveGetResp resp = ReservationConvert.INSTANCE.convert(houseReserve);
        resp.setStatusStr(RoomHouseReserveStatus.getNameByCode(resp.getStatus()));
        resp.setPaymentStatusStr(RoomHouseReservePaymentStatus.getNameByCode(resp.getPaymentStatus()));
        return resp;
    }

    @Override
    public PageResult<ReserveGetResp> page(Long roomHouseId, Integer pageNo, Integer pageSize) {
        Page<RoomHouseReserve> page = roomHouseReserveRepository.pageByRoomHouseId(roomHouseId, pageNo, pageSize);
        List<RoomHouseReserve> records = page.getRecords();
        List<ReserveGetResp> resps = ReservationConvert.INSTANCE.convert(records);
        resps.forEach(resp -> {
            resp.setStatusStr(RoomHouseReserveStatus.getNameByCode(resp.getStatus()));
            resp.setPaymentStatusStr(RoomHouseReservePaymentStatus.getNameByCode(resp.getPaymentStatus()));
        });
        PageResult<ReserveGetResp> result = new PageResult<>(resps, page.getTotal());
        return result;
    }

    @Override
    @Transactional
    public Boolean paymentSuccessful(Long reserveId, Long paymentId, LocalDateTime payTime,String payMethod) {
        log.info("预定收款成功");
        RoomHouseReserve reserve = roomHouseReserveRepository.getById(reserveId);
        if (!reserve.getStatus().equals(RoomHouseReserveStatus.TO_BE_PAID.getCode())) {
            log.error("该状态预定单不可支付：{}", RoomHouseReserveStatus.getNameByCode(reserve.getStatus()));
            return false;
        }
        Assert.isTrue(ObjectUtil.isNotEmpty(reserve), "预定单不存在");
        Long roomHouseId = reserve.getRoomHouseId();
        RoomHouse house = roomHouseRepository.getById(roomHouseId);
        //支付成功 解锁房源; 如果房源为空置状态, 则更新当前状态为待签约; 如果房源当前房态为入住中, 则新增已预定房态;
        house.setIsLock(Boolean.FALSE);
        reserve.setStatus(RoomHouseReserveStatus.RESERVED.getCode());
        reserve.setPaymentTime(payTime == null ? LocalDateTime.now() : payTime);
        reserve.setPaymentId(paymentId);
        reserve.setPaymentStatus(RoomHouseReservePaymentStatus.PROCESSED.getCode());
        RoomStateRecord currentState = roomStateRecordRepository.getByRoomIdAndIsCurrentState(roomHouseId);
        RoomStateRecord stateRecord = new RoomStateRecord();
        stateRecord.setRoomId(roomHouseId)
                .setState(RentStatusEnum.SCHEDULED.getValue())
                .setBeforeState(currentState.getState())
                .setIsCurrentState(Boolean.TRUE);
        log.info("预定支付成功-推送ES");
        //推送ES状态
        RoomelUpdateReqVO esVo = new RoomelUpdateReqVO();
        esVo.setId(roomHouseId)
                .setIsScheduled(Boolean.TRUE)
                .setIsLock(Boolean.FALSE);
        if (StrUtil.equals(RentStatusEnum.EMPTY.getValue(), currentState.getState())) {
            currentState.setIsCurrentState(false);
            roomStateRecordRepository.updateById(currentState);
            esVo.setHouseState(RentStatusEnum.SCHEDULED.getValue());
        }
        roomStateRecordRepository.save(stateRecord);
        roomHouseReserveRepository.updateById(reserve);
        roomHouseRepository.updateById(house);
        roomEsProducer.updateRoomEl(esVo);
        reserveProducer.paymentSuccess(reserve.getId(), reserve.getTenantId(), reserve.getPaymentTime(), reserve.getBookerId(), house.getApartmentId(), reserve.getDeposit());
        try {
            //预定支付成功生成收据信息
            CommonResult<ReceiptDataRespDTO> receiptConfig = receiptConfigApi.getReceiptConfig(house.getApartmentId());
            log.info("查询预订支付生成收据信息：{}", receiptConfig);
            //判断是否有配置收据 且配置开启
            if (receiptConfig.getData() != null && Objects.nonNull(receiptConfig.getData().getIsEnabled()) && 1 == receiptConfig.getData().getIsEnabled().intValue()){
                RoomReceipt roomReceipt = new RoomReceipt()
                        .setOrderId(reserve.getId())
                        .setOrderType(SourceBizTypeEnum.ROOM_RESERVE.getDesc())
                        .setInvoicingDate(payTime.toLocalDate())
                        .setCustomerName(reserve.getBooker())
                        .setCustomerIdCard(reserve.getCardNo())
                        .setAmount(reserve.getDeposit())
                        .setPayMethod(payMethod)
                        .setDrawerName(reserve.getSalesperson())
                        .setPayeeName(reserve.getSalesperson())
                        .setFinancialSealUrl(receiptConfig.getData().getFinancialSealUrl())
                        .setIsCancel(0)
                        .setBookerId(reserve.getBookerId());
                roomReceiptMapper.insert(roomReceipt);
                // 生成收据pdf
                String pdfUrl = roomReceiptService.generateReceiptPdf(roomReceipt);
                if (StringUtils.isNotBlank(pdfUrl)){
                    RoomReceipt updateRoomReceipt = new RoomReceipt();
                    updateRoomReceipt.setId(roomReceipt.getId());
                    updateRoomReceipt.setPdfUrl(pdfUrl);
                    roomReceiptMapper.updateById(updateRoomReceipt);
                }
            }
        } catch (Exception e) {
            log.error("预定支付成功生成收据信息失败，异常信息：", e);
        }
        return true;
    }

    @Override
    @Transactional
    public Boolean cancel(Long reserveId, String reason) {
        RoomHouseReserve reserve = roomHouseReserveRepository.getById(reserveId);
        Assert.isTrue(ObjectUtil.isNotEmpty(reserve), "预定单不存在");

        RoomelUpdateReqVO esVo = new RoomelUpdateReqVO();
        Long roomHouseId = reserve.getRoomHouseId();
        RoomHouse house = roomHouseRepository.getById(roomHouseId);
        if (RoomHouseReserveStatus.TO_BE_PAID.getCode().equals(reserve.getStatus())) {

        } else if (RoomHouseReserveStatus.RESERVED.getCode().equals(reserve.getStatus())) {
            //已支付取消
            List<RoomStateRecord> stateRecordList = roomStateRecordRepository.listByRoomIdAndIsCurrentState(roomHouseId);
            //回滚房态到预定的前置房态, 空房 | 入住中
            RoomStateRecord stateRecord = stateRecordList.stream().filter(record -> RentStatusEnum.SCHEDULED.getValue().equals(record.getState())).findFirst().orElse(null);
            if (stateRecord != null) {
                stateRecord.setIsCurrentState(false);
                roomStateRecordRepository.updateById(stateRecord);
            }
            Optional<RoomStateRecord> stayingInRecord = stateRecordList.stream().filter(record -> RentStatusEnum.STAYINGIN.getValue().equals(record.getState())).findFirst();
            if (!stayingInRecord.isPresent()) {
                RoomStateRecord currentStateRecord = new RoomStateRecord();
                currentStateRecord.setIsCurrentState(Boolean.TRUE)
                        .setState(RentStatusEnum.EMPTY.getValue())
                        .setRoomId(roomHouseId)
                        .setBeforeState(RentStatusEnum.SCHEDULED.getValue())
                        .setTenantId(house.getTenantId());
                roomStateRecordRepository.save(currentStateRecord);
                esVo.setHouseState(RentStatusEnum.EMPTY.getValue());
            } else {
                esVo.setHouseState(RentStatusEnum.STAYINGIN.getValue());
            }
        } else {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "该预定不可取消");
        }
        LocalDateTime now = LocalDateTime.now();
        house.setIsLock(Boolean.FALSE);
        reserve.setStatus(RoomHouseReserveStatus.CANCELED.getCode());
        reserve.setPaymentStatus(RoomHouseReservePaymentStatus.CANCELED.getCode());
        reserve.setCancelTime(now);
        //ESvo
        esVo.setId(roomHouseId);
        esVo.setIsLock(Boolean.FALSE);
        esVo.setIsScheduled(Boolean.FALSE);
        roomHouseRepository.updateById(house);
        roomHouseReserveRepository.updateById(reserve);
        roomEsProducer.updateRoomEl(esVo);
        reserveProducer.paymentCancel(reserve.getId(), reserve.getTenantId(), reserve.getBookerId(), house.getApartmentId());
        return true;
    }

    @Override
    public Boolean update(ReserveUpdateReq req) {
        RoomHouseReserve roomHouseReserve = ReservationConvert.INSTANCE.convert(req);
        //创建预定人信息
        String booker = req.getBooker();
        String bookerPhone = req.getBookerPhone();
        String cardNo = req.getCardNo();
        MemberUserReqDTO userDto = new MemberUserReqDTO();
        userDto.setMobile(bookerPhone);
        userDto.setCardNo(cardNo);
        userDto.setName(booker);
        CommonResult<MemberUserRespDTO> userResult = customerUserApi.getUserInfo(userDto);
        if (!userResult.isSuccess()) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "预定人信息创建失败");
        }
        Long bookerId = userResult.getData().getId();
        roomHouseReserve.setBookerId(bookerId);
        roomHouseReserveRepository.updateById(roomHouseReserve);

//        // 创建延迟任务, 处理待支付取消和已预定取消
//        long depositPaymentTermMinutes = LocalDateTimeUtil.between(LocalDateTime.now(), roomHouseReserve.getDepositPaymentTerm()).toMinutes() + 1;
//        long expirationDateMinutes = LocalDateTimeUtil.between(LocalDateTime.now(), roomHouseReserve.getExpirationDate()).toMinutes() + 1;
//        delayJobService.addDelayJob(DEPOSIT_PAYMENT_TERM, roomHouseReserve.getId(), depositPaymentTermMinutes, TimeUnit.MINUTES);
//        delayJobService.addDelayJob(EXPIRATION_DATE, roomHouseReserve.getId(), expirationDateMinutes, TimeUnit.MINUTES);
        return true;
    }

    private static final String BILL_TYPE = "定金账单";

    @Override
    public PageResult<ReserveBillPageResp> billPage(ReserveBillPageReq req) {
        Page<ReserveBillPageResp> page = roomHouseReserveRepository.billPage(req);
        List<ReserveBillPageResp> records = page.getRecords();
        records.forEach(s -> {
            s.setBillType(BILL_TYPE);
            s.setPaymentStatusStr(RoomHouseReservePaymentStatus.getNameByCode(s.getPaymentStatus()));
            s.setStatusStr(RoomHouseReserveStatus.getNameByCode(s.getStatus()));
            if(StringUtils.isNotBlank(s.getPaymentStatus())) {
                if (RoomHouseReserveStatus.TO_BE_PAID.getCode().equals(s.getStatus())) {
                    s.setReceivable(s.getBillAmount());
                } else {
                    s.setReceivable(BigDecimal.ZERO);
                }
            }
        });
        PageResult<ReserveBillPageResp> result = new PageResult<>(page.getRecords(), page.getTotal());
        return result;
    }

    @Override
    public ReserveGetResp get(Long id) {
        RoomHouseReserve houseReserve = roomHouseReserveRepository.getById(id);
        if (houseReserve == null) {
            return null;
        }
        ReserveGetResp resp = ReservationConvert.INSTANCE.convert(houseReserve);
        resp.setStatusStr(RoomHouseReserveStatus.getNameByCode(resp.getStatus()));
        resp.setPaymentStatusStr(RoomHouseReservePaymentStatus.getNameByCode(resp.getPaymentStatus()));
        return resp;
    }

    @Override
    public ExportBaseVo billExport(ReserveBillPageReq req) {
        Long totalCount = roomHouseReserveRepository.billCount(req);
        if (totalCount <= 0) {
            throw new ServiceException(ErrorCodeConstants.RESERVE_BILL_NOT_EXISTS);
        }
        int pageSize = 5000;
        int totalPage = (int) (totalCount / pageSize);
        if (totalCount % pageSize != 0) {
            totalPage++;
        }
        String fileName = configValues.getNfsPath() + File.separator + "预定账单导出.xlsx";
        File file = new File(fileName);
        File parentDir = file.getParentFile();
        if (!parentDir.exists()) {
            parentDir.mkdirs();  // 创建路径中的目录
        }
        ExcelWriter excelWriter = EasyExcel.write(fileName, ReserveBillExportVo.class).build();
        WriteSheet sheet = EasyExcel.writerSheet("sheet1").build();
        req.setPageSize(pageSize);
        for (int i = 1; i <= totalPage; i++) {
            req.setPageNo(i);
            Page<ReserveBillPageResp> page = roomHouseReserveRepository.billPage(req);
            List<ReserveBillPageResp> records = page.getRecords();
            List<ReserveBillExportVo> vos = records.stream().map(s -> {
                ReserveBillExportVo vo = new ReserveBillExportVo();
                BeanUtils.copyProperties(s, vo);
                vo.setBillType(BILL_TYPE);
                vo.setStatusStr(RoomHouseReserveStatus.getNameByCode(s.getStatus()));
                if (RoomHouseReserveStatus.TO_BE_PAID.getCode().equals(s.getStatus())) {
                    vo.setReceivable(s.getBillAmount());
                } else {
                    vo.setReceivable(BigDecimal.ZERO);
                }
                return vo;
            }).collect(Collectors.toList());
            excelWriter.write(vos, sheet);
        }
        excelWriter.finish();
        //上传到oos返回URL
        String url = oosFileService.oosUploadFile(new File(fileName));
        ExportBaseVo resp = new ExportBaseVo();
        resp.setUrl(url);
        resp.setFileName("预定账单导出.xlsx");
        return resp;
    }

    @Override
    public ExportBaseVo reserveExport(ReserveBillPageReq req) {
        Long totalCount = roomHouseReserveRepository.billCount(req);
        if (totalCount <= 0) {
            throw new ServiceException(ErrorCodeConstants.RESERVE_BILL_NOT_EXISTS);
        }
        int pageSize = 5000;
        int totalPage = (int) (totalCount / pageSize);
        if (totalCount % pageSize != 0) {
            totalPage++;
        }
        String fileName = configValues.getNfsPath() + File.separator + "预定单导出.xlsx";
        File file = new File(fileName);
        File parentDir = file.getParentFile();
        if (!parentDir.exists()) {
            parentDir.mkdirs();  // 创建路径中的目录
        }
        ExcelWriter excelWriter = EasyExcel.write(fileName, ReserveExportVo.class).build();
        WriteSheet sheet = EasyExcel.writerSheet("sheet1").build();
        req.setPageSize(pageSize);
        for (int i = 1; i <= totalPage; i++) {
            req.setPageNo(i);
            Page<ReserveBillPageResp> page = roomHouseReserveRepository.billPage(req);
            List<ReserveBillPageResp> records = page.getRecords();
            List<ReserveExportVo> vos = records.stream().map(s -> {
                ReserveExportVo vo = new ReserveExportVo();
                BeanUtils.copyProperties(s, vo);
                vo.setStatusStr(RoomHouseReserveStatus.getNameByCode(s.getStatus()));
                vo.setBillAmount(s.getBillAmount());
                return vo;
            }).collect(Collectors.toList());
            excelWriter.write(vos, sheet);
        }
        excelWriter.finish();
        //上传到oos返回URL
        String url = oosFileService.oosUploadFile(new File(fileName));
        ExportBaseVo resp = new ExportBaseVo();
        resp.setUrl(url);
        resp.setFileName("预定单导出.xlsx");
        return resp;
    }


    /**
     * 查询我的预定
     *
     * @param pageNum
     * @param pageSize
     * @param payState    支付状态 1：待支付 2：待签约 3：已取消 4：已签约 5：已退订 6：失效
     * @param bookerPhone
     * @return
     */
    @Override
    public CommonResult<PageResult<MyReservePageRespVO>> getMyReserve(Integer pageNum, Integer pageSize, Integer payState, @NonNull String bookerPhone) {
        // 预定
        List<MyReservePageRespVO> respVOS = new ArrayList<>();
        Page<RoomHouseReserve> page = roomHouseReserveRepository.getMyReserve(pageNum, pageSize, payState, bookerPhone);
        page.getRecords().forEach(roomHouseReserve -> {
            RoomHouse roomHouse = roomHouseRepository.myGetById(roomHouseReserve.getRoomHouseId());
            MyReservePageRespVO respVO = new MyReservePageRespVO();
            respVO.setReserveId(roomHouseReserve.getId());
            respVO.setDeposit(roomHouseReserve.getDeposit());
            respVO.setRemark(roomHouseReserve.getRemark());
            respVO.setCreateTime(roomHouseReserve.getCreateTime());
            respVO.setCheckInDate(roomHouseReserve.getCheckInDate());
            respVO.setPaymentStatus(this.convert(roomHouseReserve.getStatus()));
            respVO.setSpace(roomHouse.getSpace().toString());
            if (roomHouse.getIsConcentrated()) {
                RoomLayout roomLayout = roomLayoutRepository.myGetById(roomHouse.getLayoutId());
                respVO.setSpace(roomLayout.getSpaceMin());
            }
            RoomHouseType roomHouseType = roomHouseTypeRepository.myGetById(roomHouse.getRoomHouseTypeId());
            respVO.setRoomHouseTypeName(roomHouseType.getName());
            respVO.setRoomHouseName(RoomHouseUtil.getHouseFullName(roomHouse));
            respVO.setReserveNotify(configValues.getReserveNotify());
            respVOS.add(respVO);
        });
        PageResult<MyReservePageRespVO> pageResult = new PageResult<>(respVOS, page.getTotal());
        return CommonResult.success(pageResult);
    }

    /**
     * 根据用户ID获取预定信息
     *
     * @param userId   用户id
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public PageResult<GetByUserIdRespVO> getByUserId(Long userId, Integer pageNo, Integer pageSize) {
        Page<GetByUserIdRespVO> respVOPage = roomHouseReserveRepository.getByBookerId(userId, pageNo, pageSize);
        List<GetByUserIdRespVO> records = respVOPage.getRecords();
        records.forEach(getByUserIdRespVO -> {
            getByUserIdRespVO.setPaymentStatus(RoomHouseReservePaymentStatus.getNameByCode(getByUserIdRespVO.getPaymentStatus()));
            getByUserIdRespVO.setStatus(RoomHouseReserveStatus.getNameByCode(getByUserIdRespVO.getStatus()));
            StringBuilder sb = new StringBuilder();
            sb.append(getByUserIdRespVO.getArea());
            sb.append(getByUserIdRespVO.getBuildingNo());
            sb.append("栋");
            if(!getByUserIdRespVO.getIsConcentrated()){
                sb.append(getByUserIdRespVO.getUnitNo());
                sb.append("单元");
            }
            sb.append(getByUserIdRespVO.getRoomHouseName());
            getByUserIdRespVO.setRoomHouseFullName(sb.toString());
        });
        return new PageResult<>(records, respVOPage.getTotal());
    }

    @Override
    public void updateMember(Long userId, String mobile) {
        roomHouseReserveRepository.updateMember(userId,mobile);
    }

    @Override
    @TenantIgnore
    public RoomReserveExportResp templateDownload(Long apartmentId) {
        String fileName = "预定账单模版.xlsx";
        List<RoomHouse> list = roomHouseRepository.selectAll(apartmentId);
        List<ReserveTemplateExportVO> reserveList = new ArrayList<>();
        for (RoomHouse roomHouse : list) {
            String houseNo = roomHouse.getName();
            String area = roomHouse.getArea();
            String unitNo = roomHouse.getUnitNo();
            String buildingNo = roomHouse.getBuildingNo();
            Long id = roomHouse.getId();
            String finalName;
            Boolean isConcentrated = roomHouse.getIsConcentrated();
            if (isConcentrated) {
                finalName = area + buildingNo + "栋" + houseNo;
            } else {
                finalName = area + buildingNo + "栋" + unitNo + "单元" + houseNo;
            }
            ReserveTemplateExportVO reserveTemplateExportVO = new ReserveTemplateExportVO();
            reserveTemplateExportVO.setRoomHouseID(id.toString());
            reserveTemplateExportVO.setRoomHouseName(finalName);
            reserveTemplateExportVO.setBillType("定金账单");
            reserveTemplateExportVO.setBillingStatus("已处理");
            reserveList.add(reserveTemplateExportVO);
        }
        ExcelWriter excelWriter = EasyExcel.write(fileName, ReserveTemplateExportVO.class).build();
        WriteSheet sheet = EasyExcel.writerSheet("sheet1").head(ReserveTemplateExportVO.class).build();
        excelWriter.write(reserveList, sheet);
        excelWriter.finish();
        String url = oosFileService.oosUploadFile(new File(fileName));
        RoomReserveExportResp resp = new RoomReserveExportResp();
        resp.setUrl(url);
        resp.setFileName(fileName);
        return resp;
    }

    @Override
    public CommonResult<String> reserveImport(String fileUrl) {
//        try (InputStream is = oosFileService.oosDownloadFile(fileUrl)) {
//            EasyExcel.read(is, ReserveTemplateExportVO.class, new ReadingRoomReserveImportListener(roomHouseRepository, customerUserApi,roomEsProducer,roomStateRecordRepository,roomHouseReserveRepository,codeUtil)).sheet().doRead();
//        } catch (IOException e) {
//            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "文件不存在");
//        } catch (ExcelDataConvertException e) {
//            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "数据格式不正确");
//        }
        InputStream is = oosFileService.oosDownloadFile(fileUrl);
        EasyExcel.read(is, ReserveTemplateExportVO.class, new ReadingRoomReserveImportListener(roomHouseRepository, customerUserApi,roomEsProducer,roomStateRecordRepository,roomHouseReserveRepository,codeUtil,delayJobService)).sheet().doRead();
        return CommonResult.success("预定账单导入成功");
    }

    private String convert(String status) {
        if (RoomHouseReserveStatus.TO_BE_PAID.getCode().equals(status)) {
            return "待支付";
        }
        if (RoomHouseReserveStatus.RESERVED.getCode().equals(status)) {
            return "待签约";
        }
        if (RoomHouseReserveStatus.CANCELED.getCode().equals(status)) {
            return "已取消";
        }
        if (RoomHouseReserveStatus.SINGED.getCode().equals(status)) {
            return "已签约";
        }
        if (RoomHouseReserveStatus.RETIRED.getCode().equals(status)) {
            return "已退定";
        }
        if (RoomHouseReserveStatus.FAILURE.getCode().equals(status)) {
            return "失效";
        }
        return "";
    }


    @Override
    public List<RoomReserveWithdrawalDetail> getWithdrawDetail(Long reserveId, Integer reasonId) {
        RoomHouseReserve reserve = roomHouseReserveRepository.getById(reserveId);
        if (Objects.isNull(reserve)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "预定不存在");
        }
        List<RoomReserveWithdrawalDetail> roomReserveWithdrawalDetails = generateWithdrawDetail(reserve, reasonId);
        return roomReserveWithdrawalDetails;
    }

    private List<RoomReserveWithdrawalDetail> generateWithdrawDetail(RoomHouseReserve reserve, Integer reasonId){
        List<RoomReserveWithdrawalDetail> roomReserveWithdrawalDetails = new ArrayList<>();
        Long apartmentId = reserve.getApartmentId();
        if (Objects.isNull(apartmentId)){
            RoomHouse house = roomHouseRepository.getById(reserve.getRoomHouseId());
            if (Objects.isNull(house)){
                throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "房源不存在");
            }
            apartmentId = house.getApartmentId();
        }
        ReservationConfigGetResp config = roomReservationConfigService.getConfig(apartmentId);
        if (Objects.isNull(config)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "预定配置不存在");
        }
        if (reasonId.intValue() == ReserveWithdrawReasonEnum.DEFAULT.getValue().intValue()){
            Integer noRefundPercent = config.getNoRefundPercent();
            BigDecimal noRefundAmount = reserve.getDeposit().multiply(new BigDecimal(noRefundPercent.toString())).divide(new BigDecimal("100"));
            RoomReserveWithdrawalDetail depositFee = new RoomReserveWithdrawalDetail();
            depositFee.setFeeType(ReserveWithdrawFeeEnum.DEPOSIT.getValue());
            depositFee.setFeeName(ReserveWithdrawFeeEnum.DEPOSIT.getName());
            depositFee.setTotalAmount(reserve.getDeposit());
            depositFee.setActualAmount(reserve.getDeposit().subtract(noRefundAmount));
            depositFee.setFlowType(OrderFeeFlowTypeEnum.OUTFLOW.getCode());
            roomReserveWithdrawalDetails.add(depositFee);
            RoomReserveWithdrawalDetail breakPenaltyFee = new RoomReserveWithdrawalDetail();
            breakPenaltyFee.setFeeType(ReserveWithdrawFeeEnum.BREAK_PENALTY.getValue());
            breakPenaltyFee.setFeeName(ReserveWithdrawFeeEnum.BREAK_PENALTY.getName());
            breakPenaltyFee.setTotalAmount(noRefundAmount);
            breakPenaltyFee.setActualAmount(noRefundAmount);
            breakPenaltyFee.setFlowType(OrderFeeFlowTypeEnum.INFLOW.getCode());
            roomReserveWithdrawalDetails.add(breakPenaltyFee);
        }else if (reasonId.intValue() == ReserveWithdrawReasonEnum.NEGOTIATE.getValue().intValue()){
            Integer consultRefundPercent = config.getConsultRefundPercent();
            BigDecimal consultRefundAmount = reserve.getDeposit().multiply(new BigDecimal(consultRefundPercent.toString())).divide(new BigDecimal("100"));
            RoomReserveWithdrawalDetail depositFee = new RoomReserveWithdrawalDetail();
            depositFee.setFeeType(ReserveWithdrawFeeEnum.DEPOSIT.getValue());
            depositFee.setFeeName(ReserveWithdrawFeeEnum.DEPOSIT.getName());
            depositFee.setTotalAmount(reserve.getDeposit());
            depositFee.setActualAmount(consultRefundAmount);
            depositFee.setFlowType(OrderFeeFlowTypeEnum.OUTFLOW.getCode());
            roomReserveWithdrawalDetails.add(depositFee);
            RoomReserveWithdrawalDetail breakPenaltyFee = new RoomReserveWithdrawalDetail();
            BigDecimal breakPenaltyAmount = reserve.getDeposit().subtract(consultRefundAmount);
            breakPenaltyFee.setFeeType(ReserveWithdrawFeeEnum.BREAK_PENALTY.getValue());
            breakPenaltyFee.setFeeName(ReserveWithdrawFeeEnum.BREAK_PENALTY.getName());
            breakPenaltyFee.setTotalAmount(breakPenaltyAmount);
            breakPenaltyFee.setActualAmount(breakPenaltyAmount);
            breakPenaltyFee.setFlowType(OrderFeeFlowTypeEnum.INFLOW.getCode());
            roomReserveWithdrawalDetails.add(breakPenaltyFee);
        }
        return roomReserveWithdrawalDetails;
    }

    @Override
    public void reserveWithdraw(Long reserveId, Integer reasonId) {
        RoomHouseReserve reserve = roomHouseReserveRepository.getById(reserveId);
        if (Objects.isNull(reserve)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "预定不存在");
        }
        List<RoomReserveWithdrawalDetail> withdrawDetail = generateWithdrawDetail(reserve, reasonId);
        if (CollectionUtils.isEmpty(withdrawDetail)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "退定原因数据异常");
        }

        RoomReserveWithdrawalDetail depositDetail = withdrawDetail.stream().filter(d -> ReserveWithdrawFeeEnum.DEPOSIT.getValue().equals(d.getFeeType())).findFirst().orElse(null);
        reserve.setCancelTime(LocalDateTime.now());
        reserve.setCancelReason(ReserveWithdrawReasonEnum.getNameByValue(reasonId));
        reserve.setStatus(RoomHouseReserveStatus.RETIRED.getCode());
        reserve.setWithdrawStatus(ReserveWithdrawStatusEnum.PENDING.getValue());
        reserve.setWithdrawAmount(depositDetail.getActualAmount());
        reserve.setWithdrawReason(reasonId);
        // 退定金额为0 直接退定完成
        if (BigDecimal.ZERO.compareTo(reserve.getWithdrawAmount()) == 0){
            reserve.setWithdrawStatus(ReserveWithdrawStatusEnum.REFUNDED.getValue());
        }
        roomHouseReserveRepository.updateById(reserve);

        for (RoomReserveWithdrawalDetail detail : withdrawDetail) {
            detail.setReserveId(reserve.getId());
        }
        roomReserveWithdrawalDetailMapper.insertBatch(withdrawDetail);

        Long roomHouseId = reserve.getRoomHouseId();
        RoomelUpdateReqVO esVo = new RoomelUpdateReqVO();
        List<RoomStateRecord> stateRecordList = roomStateRecordRepository.listByRoomIdAndIsCurrentState(roomHouseId);
        //回滚房态到预定的前置房态, 空房 | 入住中
        RoomStateRecord stateRecord = stateRecordList.stream().filter(record -> RentStatusEnum.SCHEDULED.getValue().equals(record.getState())).findFirst().orElse(null);
        if (stateRecord != null) {
            stateRecord.setIsCurrentState(false);
            roomStateRecordRepository.updateById(stateRecord);
        }
        Optional<RoomStateRecord> stayingInRecord = stateRecordList.stream().filter(record -> RentStatusEnum.STAYINGIN.getValue().equals(record.getState())).findFirst();
        if (!stayingInRecord.isPresent()) {
            RoomStateRecord currentStateRecord = new RoomStateRecord();
            currentStateRecord.setIsCurrentState(Boolean.TRUE)
                    .setState(RentStatusEnum.EMPTY.getValue())
                    .setRoomId(roomHouseId)
                    .setBeforeState(RentStatusEnum.SCHEDULED.getValue())
                    .setTenantId(reserve.getTenantId());
            roomStateRecordRepository.save(currentStateRecord);
            esVo.setHouseState(RentStatusEnum.EMPTY.getValue());
        } else {
            esVo.setHouseState(RentStatusEnum.STAYINGIN.getValue());
        }
        //ESvo
        esVo.setId(roomHouseId);
        esVo.setIsLock(Boolean.FALSE);
        esVo.setIsScheduled(Boolean.FALSE);
        roomEsProducer.updateRoomEl(esVo);
        reserveProducer.paymentCancel(reserve.getId(), reserve.getTenantId(), reserve.getBookerId(), reserve.getApartmentId());

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void withdrawPay(ReserveWithdrawPayReq payReq) {
        RoomHouseReserve reserve = roomHouseReserveRepository.getById(payReq.getReserveId());
        if (Objects.isNull(reserve)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "预定不存在");
        }
        if (ReserveWithdrawStatusEnum.REFUNDED.getValue().equals(reserve.getWithdrawStatus())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "退定单已退款");
        }

        reserve.setWithdrawPayTime(payReq.getWithdrawPayTime());
        reserve.setWithdrawActualPayAmount(payReq.getWithdrawActualPayAmount());
        reserve.setWithdrawVoucher(payReq.getWithdrawVoucher());
        roomHouseReserveRepository.updateById(reserve);

        PayOrderCreateReqDTO reqDTO = new PayOrderCreateReqDTO();
        reqDTO.setSourceBizType(SourceBizTypeEnum.RESERVE_WITHDRAW.name());
        reqDTO.setSourceBizId(payReq.getReserveId().toString());
        reqDTO.setTrader(reserve.getBooker());
        reqDTO.setTradeTime(payReq.getWithdrawPayTime());
        reqDTO.setPayTime(payReq.getWithdrawPayTime());
        reqDTO.setAttachment(payReq.getWithdrawVoucher());
        reqDTO.setPayMethod(payReq.getPayMethod());
        payOrderApi.createOrder(reqDTO);
    }

    @Override
    public Boolean withdrawPaymentSuccessful(Long reserveId, Long paymentId, LocalDateTime payTime) {
        log.info("退定收款成功");
        RoomHouseReserve reserve = roomHouseReserveRepository.getById(reserveId);
        Assert.isTrue(ObjectUtil.isNotEmpty(reserve), "预定单不存在");
        reserve.setWithdrawStatus(ReserveWithdrawStatusEnum.REFUNDED.getValue());
        reserve.setWithdrawNum(paymentId.toString());
        roomHouseReserveRepository.updateById(reserve);
        return true;
    }


    @Override
    public PageResult<ReserveBillPageResp> withdrawBillPage(ReserveBillPageReq req) {
        if (StringUtils.isBlank(req.getWithdrawStatus())){
            req.setWithdrawStatusList(Arrays.asList(ReserveWithdrawStatusEnum.PENDING.getValue(), ReserveWithdrawStatusEnum.REFUNDED.getValue()));
        }
        PageResult<ReserveBillPageResp> result = roomHouseReserveRepository.withdrawBillPage(req);
        List<ReserveBillPageResp> records = result.getList();
        records.forEach(s -> s.setWithdrawStatusStr(StringUtils.isNotBlank(s.getWithdrawStatus())?ReserveWithdrawStatusEnum.getNameByValue(s.getWithdrawStatus()):""));
        result.setList(records);
        return result;
    }

    @Override
    public List<RoomReserveWithdrawalDetail> getWithdrawDetailById(Long reserveId) {
        RoomHouseReserve reserve = roomHouseReserveRepository.getById(reserveId);
        if (Objects.isNull(reserve)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "预定不存在");
        }
        return roomReserveWithdrawalDetailMapper.selectList(RoomReserveWithdrawalDetail::getReserveId, reserveId);
    }

    @Override
    public void paidTimeOutCancel(List<RoomHouseReserve> list) {

        //apartmentId为空
        List<RoomHouseReserve> emptyApartmentReserveList = list.stream().filter(r -> r.getApartmentId() == null).collect(Collectors.toList());
        //去除apartmentId为空后的数据
        list.removeAll(emptyApartmentReserveList);
        Map<Long, List<RoomHouseReserve>> reserveMap = list.stream().collect(Collectors.groupingBy(RoomHouseReserve::getApartmentId));

        Map<Long, List<RoomHouseReserve>> roomReserveMap = emptyApartmentReserveList.stream().collect(Collectors.groupingBy(RoomHouseReserve::getRoomHouseId));
        //查询对应apartmentId
        for (Long roomHoustId : roomReserveMap.keySet()) {
            RoomHouse house = roomHouseRepository.getById(roomHoustId);
            if (Objects.isNull(house)){
                log.error("已支付预定单超时取消生成退定单,房源{}不存在",roomHoustId);
                continue;
            }
            if (reserveMap.containsKey(house.getApartmentId())){
                List<RoomHouseReserve> reserves = reserveMap.get(house.getApartmentId());
                reserves.addAll(roomReserveMap.get(roomHoustId));
            }else {
                reserveMap.put(house.getApartmentId(),roomReserveMap.get(roomHoustId));
            }
        }

        for (Long apartmentId : reserveMap.keySet()) {
            List<RoomHouseReserve> reserveList = reserveMap.get(apartmentId);
            ReservationConfigGetResp config = roomReservationConfigService.getConfig(apartmentId);
            if (Objects.isNull(config)){
                log.error("已支付预定单超时取消生成退定单,门店{}预定配置不存在", apartmentId);
            }
            List<RoomReserveWithdrawalDetail> roomReserveWithdrawalDetails = new ArrayList<>();
            //有配置违约退定使用违约退定 否则默认全部作为违约金
            if (config.getNoRefund()){
                Integer noRefundPercent = config.getNoRefundPercent();
                for (RoomHouseReserve reserve : reserveList) {
                    BigDecimal noRefundAmount = reserve.getDeposit().multiply(new BigDecimal(noRefundPercent.toString())).divide(new BigDecimal("100"));
                    RoomReserveWithdrawalDetail depositFee = new RoomReserveWithdrawalDetail();
                    depositFee.setFeeType(ReserveWithdrawFeeEnum.DEPOSIT.getValue());
                    depositFee.setFeeName(ReserveWithdrawFeeEnum.DEPOSIT.getName());
                    depositFee.setTotalAmount(reserve.getDeposit());
                    depositFee.setActualAmount(reserve.getDeposit().subtract(noRefundAmount));
                    depositFee.setFlowType(OrderFeeFlowTypeEnum.OUTFLOW.getCode());
                    roomReserveWithdrawalDetails.add(depositFee);
                    RoomReserveWithdrawalDetail breakPenaltyFee = new RoomReserveWithdrawalDetail();
                    breakPenaltyFee.setFeeType(ReserveWithdrawFeeEnum.BREAK_PENALTY.getValue());
                    breakPenaltyFee.setFeeName(ReserveWithdrawFeeEnum.BREAK_PENALTY.getName());
                    breakPenaltyFee.setTotalAmount(noRefundAmount);
                    breakPenaltyFee.setActualAmount(noRefundAmount);
                    breakPenaltyFee.setFlowType(OrderFeeFlowTypeEnum.INFLOW.getCode());
                    roomReserveWithdrawalDetails.add(breakPenaltyFee);
                    reserve.setWithdrawAmount(noRefundAmount);
                    // 退定金额为0 直接退定完成
                    if (BigDecimal.ZERO.compareTo(reserve.getWithdrawAmount()) == 0){
                        reserve.setWithdrawStatus(ReserveWithdrawStatusEnum.REFUNDED.getValue());
                    }
                    roomHouseReserveRepository.updateById(reserve);
                }
            }else {
                for (RoomHouseReserve reserve : reserveList) {
                    RoomReserveWithdrawalDetail depositFee = new RoomReserveWithdrawalDetail();
                    depositFee.setFeeType(ReserveWithdrawFeeEnum.DEPOSIT.getValue());
                    depositFee.setFeeName(ReserveWithdrawFeeEnum.DEPOSIT.getName());
                    depositFee.setTotalAmount(reserve.getDeposit());
                    depositFee.setActualAmount(BigDecimal.ZERO);
                    depositFee.setFlowType(OrderFeeFlowTypeEnum.OUTFLOW.getCode());
                    depositFee.setReserveId(reserve.getId());
                    roomReserveWithdrawalDetails.add(depositFee);
                    RoomReserveWithdrawalDetail breakPenaltyFee = new RoomReserveWithdrawalDetail();
                    breakPenaltyFee.setFeeType(ReserveWithdrawFeeEnum.BREAK_PENALTY.getValue());
                    breakPenaltyFee.setFeeName(ReserveWithdrawFeeEnum.BREAK_PENALTY.getName());
                    breakPenaltyFee.setTotalAmount(reserve.getDeposit());
                    breakPenaltyFee.setActualAmount(reserve.getDeposit());
                    breakPenaltyFee.setFlowType(OrderFeeFlowTypeEnum.INFLOW.getCode());
                    breakPenaltyFee.setReserveId(reserve.getId());
                    roomReserveWithdrawalDetails.add(breakPenaltyFee);
                    reserve.setWithdrawAmount(reserve.getDeposit());
                    roomHouseReserveRepository.updateById(reserve);
                }
            }
            roomReserveWithdrawalDetailMapper.insertBatch(roomReserveWithdrawalDetails);
        }


    }
}
